/* SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Copyright (C) 2016-2019, LomboTech Co.Ltd.
 * Authors:
 *	lomboswer <lomboswer@lombotech.com>
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#ifndef _LOMBO_DC_PRIV_H_
#define _LOMBO_DC_PRIV_H_

#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/lombo_drm.h>
#include <linux/component.h>
#include <linux/of_device.h>
#include <linux/spinlock_types.h>

#include "csp_dpu_dc.h"
#include "lombo_crtc.h"
#include "lombo_dpu.h"
#include "lombo_drv.h"
#include "lombo_fb_sc.h"
#include "lombo_ove.h"
#include "lombo_rot.h"
#include "lombo_se.h"
#include "lombo_tcon.h"

#define DC_COLOR_ENHANCE_MAX_VALUE	100
#define DC_CM_MIN_SAT			0
#define DC_CM_MAX_SAT			100
#define LOMBO_DC_ASSERT(x) WARN_ON(!(x))
#define LOMBO_DC_BLK_BL_NUM 16

struct lombo_crtc;
struct lombo_tcon;
struct lombo_dc;

enum {
	LOMBO_CSFMT_IN_RGB = 1 << LOMBO_CSFMT_RGB,
	LOMBO_CSFMT_IN_YUV = 1 << LOMBO_CSFMT_YUV,
};

enum {
	LOMBO_BLK_COMMIT_FLAG_ENABLE = 1,
};

enum {
	LOMBO_COLOR_ENABLE = 0,
	LOMBO_CE_BRIGHTNESS,
	LOMBO_CE_SATURATION,
	LOMBO_CE_CONTRAST,
	LOMBO_CM_SAT_RED,
	LOMBO_CM_SAT_ORANGE,
	LOMBO_CM_SAT_YELLOW,
	LOMBO_CM_SAT_GREEN,
	LOMBO_CM_SAT_CYAN,
	LOMBO_CM_SAT_BLUE,
	LOMBO_CM_SAT_PURPLE,
	LOMBO_CM_SAT_MAGENTA,
};

struct lombo_dc_cfg {
	uint8_t win_num:4;
	uint8_t no_win_sc:1;
	uint8_t no_hw_cursor:1;
	uint8_t no_ifb:1;
	uint8_t has_se_hmir:1; /* todo: mv to dpu_top */
	uint8_t has_cm:1;
	uint8_t res:7;
};

struct lombo_dc_blk_bl {
	struct drm_plane base;
	struct lombo_dc_blk *blk;

	uint32_t id;
	dpu_fb_t dpu_fb;
	dpu_rectangle_t rect;
	uint8_t enable;
	uint8_t dirty;
};

struct lombo_dc_blk {
	struct lombo_dc *dc;

	struct lombo_dc_blk_bl bl_array[LOMBO_DC_BLK_BL_NUM];
	uint32_t enable_mask;

	struct drm_gem_cma_object *cursor_cma_obj;

	uint8_t opaque_fb_num;
};

struct lombo_dc_win {
	struct drm_plane base;
	struct lombo_dc *dc;

	uint8_t id; /* hw id */
	uint16_t alpha; /* only for debugfs dump */

	struct lombo_fb_cfg fb_cfg;
	struct lombo_se_fb_cfg se_fb_cfg;
	struct lombo_se *se;
	uint8_t se_commit;
	uint8_t se_disable;
	uint8_t se_rming;
	struct lombo_se *rm_se;
	spinlock_t selock;

	struct lombo_ove_fb_cfg ove_fb_cfg;
	struct lombo_ove *ove;
	struct lombo_ove *commit_ove;

	/* opaque rect */
	int opaque_num;
	struct drm_lombo_rect_wh opaque[4];
	struct drm_lombo_rect_wh trp; /* transparent */
};

struct lombo_color {
	dc_enhance_info_t ce;
	dc_cm_info_t cm;
	uint8_t color_enable:1;
	uint8_t color_commit:1;
	uint8_t ce_info_changed:1;
	uint8_t cm_curve_changed:1;
	uint8_t res:4;
};

struct lombo_dc_fbdev_info {
	const struct drm_format_info *format;
	uint32_t width;
	uint32_t height;
	uint32_t pitch;

	uint8_t num;
	uint8_t fb_cur; /* cur id of access-fb by hw */
	uint8_t fb_rotated;
	struct drm_framebuffer *fbs[2];
	struct drm_framebuffer *vfb; /* the virtual fb of fbdev */

	uint32_t rotate;
	struct lombo_rot_client *rot;
};

struct lombo_dc {
	struct device *dev;
	struct drm_device *drm;
	struct lombo_tcon *tcon;
	struct lombo_crtc *ecrtc;

	/* add to drv dc_list */
	struct list_head list;

	void __iomem *reg;
	struct lombo_dpu_clk *clk;

	/* store win/blockliner sequently */
	struct drm_plane **planes;

	int dpms;

	/* screen info */
	uint32_t scn_w;
	uint32_t scn_h;
	uint32_t scn_fmt;

	struct lombo_color color;

	/* hw cfg */
	const struct lombo_dc_cfg *cfg;
	uint8_t id;

	/* actual_fbdev info for vfbdev */
	struct lombo_dc_fbdev_info actual_fbdev;

	struct work_struct page_flip_work;

	bool user_blk;
	struct lombo_dc_blk *blk;
	bool sleep;
	struct notifier_block nb;
};

static inline struct lombo_dc_win *to_lombo_dc_win(struct drm_plane *plane)
{
	return container_of(plane, struct lombo_dc_win, base);
}

static inline struct lombo_dc_blk_bl *to_lombo_dc_blk_bl(
	struct drm_plane *plane)
{
	return container_of(plane, struct lombo_dc_blk_bl, base);
}

int lombo_dc_convert_drm_format(int format);
int lombo_dc_blk_update_fbdev_for_win(struct lombo_dc *dc,
	struct lombo_dc_win *win, struct drm_framebuffer *fb);

#endif /* _LOMBO_DC_PRIV_H_ */
